package com.hongji.lms5xxcommunicator.service.imp;

import com.hongji.lms5xxcommunicator.entity.ScanPointEntity;
import com.hongji.lms5xxcommunicator.grid.config.RasterGridHolder;
import com.hongji.lms5xxcommunicator.mapper.ScanPointDataMapper;
import com.hongji.lms5xxcommunicator.service.ScanPointDataService;
import com.hongji.lms5xxcommunicator.storage.EpochManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class ScanPointDataServiceImp implements ScanPointDataService {

    @Value("${grid.base.dx}") private double DX0;
    @Value("${grid.base.dy}") private double DY0;

    private final ScanPointDataMapper mapper;
    private final RasterGridHolder rasterGridHolder; // 可能用于越界判定，你现在没用到也保留
    private final EpochManager epochManager;

    private final java.util.concurrent.atomic.AtomicLong frameSeq = new java.util.concurrent.atomic.AtomicLong(0L);

    /**
     * 批量写库（来自缓冲 flusher）。
     * 逻辑：分帧 → 量化(ix,iy) → 按 ix 分组 → 仅删本会话该列 → UPSERT
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchUpsertPoints(List<ScanPointEntity> points) {
        if (points == null || points.isEmpty()) {
            log.debug("batchUpsertPoints：输入为空，跳过");
            return 0;
        }
        final long frame = frameSeq.incrementAndGet();
        final long epoch = epochManager.getCurrent();

        Map<Integer, List<ScanPointEntity>> byIx = new HashMap<>();
        for (ScanPointEntity p : points) {
            if (p == null || p.getX() == null || p.getY() == null || p.getZ() == null) continue;

            int ix = (int) Math.floor(p.getX() / DX0);
            int iy = (int) Math.floor(p.getY() / DY0);

            p.setIx(ix);
            p.setIy(iy);
            p.setLastFrame(frame);
            p.setEpoch(epoch); // ⭐ 写入 epoch

            byIx.computeIfAbsent(ix, k -> new ArrayList<>()).add(p);
        }

        int affected = 0;
        for (Map.Entry<Integer, List<ScanPointEntity>> e : byIx.entrySet()) {
            int ix = e.getKey();
            List<ScanPointEntity> rows = e.getValue();
            if (rows.isEmpty()) continue;

            // 仅清理“本会话”的该列；不会误删历史会话
            mapper.deleteStaleByIx(epoch, ix);

            // UPSERT（可用 insertBatchSomeColumn 或 upsertSnapshotBatch，语义一致）
            affected += mapper.upsertSnapshotBatch(epoch, rows, frame);
        }
        log.info("batchUpsertPoints：epoch={}, frame={}, 列数={}, 影响行={}",
                epoch, frame, byIx.size(), affected);
        return affected;
    }
}
